//==========================================================================
// Copyright (c) 2000-2006,  Elastos, Inc.  All Rights Reserved.
//==========================================================================

#include <convert.h>
#include <winhack.h>
#include <eltypes.h>

void ConvertSYStimeToVMtime(SystemTime ezStdtime, SystemTime *ezMVtime)//get system time
{
    ezMVtime->microseconds = ezStdtime.microseconds;

    if(0 != g_TimeConver.m_isPositive) {
        ezMVtime->seconds = (ulong_t)(ezStdtime.seconds + g_TimeConver.m_Seconds);
    } else {
        if((ezStdtime.seconds - g_TimeConver.m_Seconds) >= 0) {//Do not turn to zero
            ezMVtime->seconds = (ulong_t)(ezStdtime.seconds - g_TimeConver.m_Seconds);
        } else {
            ezMVtime->seconds = (ulong_t)( 0xffffffff - g_TimeConver.m_Seconds + ezStdtime.seconds + 0x1);//0x100000000 is overfloat so 0x100000000 = 0xffffffff + 0x1
        }
    }
    //printf("ConvertSYStimeToVMtime ezMVtime.seconds: %x\n", ezMVtime->seconds);
    //printf("ConvertSYStimeToVMtime ezStdtime.seconds: %x\n", ezStdtime.seconds);
    //printf("ConvertSYStimeToVMtime g_TimeConver.m_Seconds: %x\n", g_TimeConver.m_Seconds);
}

void ConvertVMtimeToDiffTime(SystemTime ezStdtime, SystemTime ezMVtime)//set system time
{
    //printf("1ConvertVMtimeToDiffTime ezMVtime.seconds: %x\n", ezMVtime.seconds);
    //printf("1ConvertVMtimeToDiffTime ezStdtime.seconds: %x\n", ezStdtime.seconds);
    //printf("1ConvertVMtimeToDiffTime g_TimeConver.m_Seconds: %x\n", g_TimeConver.m_Seconds);

    if((ezMVtime.seconds -ezStdtime.seconds) >= 0) {
        g_TimeConver.m_Seconds = ezMVtime.seconds -ezStdtime.seconds;
        g_TimeConver.m_isPositive = 1;
    } else {
        g_TimeConver.m_Seconds = ezStdtime.seconds - ezMVtime.seconds ;
        g_TimeConver.m_isPositive = 0;
    }
    //printf("ConvertVMtimeToDiffTime ezMVtime.seconds: %x\n", ezMVtime.seconds);
    //printf("ConvertVMtimeToDiffTime ezStdtime.seconds: %x\n", ezStdtime.seconds);
    //printf("ConvertVMtimeToDiffTime g_TimeConver.m_Seconds: %x\n", g_TimeConver.m_Seconds);
}

void ConvertTimeZoneInfoFromVM(LONG BiasIn, LONG * pBiasOut)
{
    *pBiasOut = BiasIn + g_TimeConver.Bias;
}

void ConvertTimeZoneInfoToVM(LONG BiasStd, long pBiasSet)
{
    g_TimeConver.Bias = pBiasSet - BiasStd;
}

void ConvertSystimeToEzTime(SYSTEMTIME systime, SystemTime* eztime)
{
    int mon  = systime.wMonth;
    int year = systime.wYear;
    if (0 >= (int) (mon -= 2)) {        // 1..12 -> 11,12,1..10
        mon += 12;                      // Puts Feb last since it has leap day
        year -= 1;
    }

    ULONG t = (((
            (ULONG)(year/4 - year/100 + year/400 + 367*mon/12 + systime.wDay) +
        	year*365 - 719499
        )*24 + systime.wHour                  // now have hours
      )*60 + systime.wMinute                  // now have minutes
    )*60 + systime.wSecond;                   // finally seconds
    eztime->seconds = t;
    eztime->microseconds = systime.wMilliseconds * 1000;

}

void ConvertEzTimeToSystime(SystemTime eztime, PSYSTEMTIME systime)
{
    UCHAR s_DaysInMonth1[] = {0,31,29,31,30,31,30,31,31,30,31,30,31};
    UCHAR s_DaysInMonth0[] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
    systime->wMilliseconds = (WORD)(eztime.microseconds/1000);
    ULONG tm = (ULONG)(eztime.seconds);//unit is second
    systime->wSecond    = (WORD) (tm % 60); tm /= 60;
    systime->wMinute    = (WORD) (tm % 60); tm /= 60;
    systime->wHour      = (WORD) (tm % 24); tm /= 24;   // tm becomes day
    systime->wDayOfWeek = (WORD) ((tm + 4) % 7);        // it's Thursday on 1/1/1970

    // count from 1970. year 2100 will be count as a leap year falsely
    // due to simplify of IS_LEAP_YEAR algorithm.
    //
    UINT year = 70;
    while (1) {
        if (IS_LEAP_YEAR(year + 300)) {
            if (tm < 366) break; else tm -= 366;
        } else {
            if (tm < 365) break; else tm -= 365;
        }
        year++;
    }
    UINT month = 1;
    UCHAR *  DaysInMonth = IS_LEAP_YEAR(year + 300) ? s_DaysInMonth1 : s_DaysInMonth0;
    while (1) {
        if (tm < DaysInMonth[month]) break;
        else tm -= DaysInMonth[month];
        month++;
    }
    systime->wYear  = year + 1900;
    systime->wMonth = month;
    systime->wDay   = (WORD)++tm;

}

/*DWORD ContextToWin(PDOMAININFO pDomainInfo)
{
    return ((pDomainInfo == CTX_SAME_PROCESS)? (CLSCTX_INPROC_SERVER) : \
            ((pDomainInfo == CTX_DIFF_PROCESS)? (CLSCTX_LOCAL_SERVER) : \
            ((pDomainInfo == CTX_USER_2_KERN)? (CLSCTX_INPROC_SERVER) : \
            ((pDomainInfo == CTX_KERN_2_USER)? (CLSCTX_INPROC_SERVER) : \
            ((pDomainInfo == CTX_DIFF_MACHINE)? (CLSCTX_REMOTE_SERVER) : \
            CLSCTX_INPROC_SERVER)))));
}*/

#ifdef _GNUC
const UINT64 bias64 = 0x019db1ded53e8000LL;//1970.01.01 - 1601.01.01
#else
const UINT64 bias64 = 0x019db1ded53e8000;//1970.01.01 - 1601.01.01
#endif

void ConvertFileTimeToEzTime(FILETIME filetime, SystemTime* eztime)
{
    UINT64 tmptime;
    tmptime = *(UINT64*)&filetime - bias64;
    eztime->seconds = (UINT32)(tmptime / 10000000);
    eztime->microseconds = (UINT32)((tmptime % 10000000) / 10);
}
